package com.goldsprite.gameframeworks.ecs.system;

import com.goldsprite.gameframeworks.ecs.ComponentManager;
import com.goldsprite.gameframeworks.ecs.IRunnable;
import com.goldsprite.gameframeworks.ecs.component.IComponent;
import com.goldsprite.gameframeworks.ecs.entity.GObject;

import java.util.BitSet;
import java.util.List;

public abstract class BaseSystem implements IRunnable {
	private IRunnableFields fields = new IRunnableFields();
	
	protected GameSystem gm;
	private boolean isEnabled = true;
	protected BitSet componentMask;
	private Class<? extends IComponent>[] interestComponents;

	public BaseSystem() {
		initIRunnable();
		this.gm = GameSystem.getInstance();

		// 自动解析注解
		GameSystemInfo info = this.getClass().getAnnotation(GameSystemInfo.class);
		if (info != null) {
			this.interestComponents = info.interestComponents();
			buildComponentMask();
		}

		// 自动注册到GameSystem
		GameSystem.getInstance().registerSystem(this);
	}
	
	@Override
	public IRunnable.IRunnableFields getIRunnableFields() {
		return fields;
	}

	private void buildComponentMask() {
		if (interestComponents != null && interestComponents.length > 0) {
			componentMask = new BitSet();
			for (Class<? extends IComponent> compType : interestComponents) {
				componentMask.set(ComponentManager.getComponentId(compType));
			}
		}
	}

	protected List<GObject> getEntitiesWithComponents(Class<? extends IComponent>... componentTypes) {
		return ComponentManager.getEntitiesWithComponents(componentTypes);
	}

	protected List<GObject> getInterestEntities() {
		if (interestComponents != null && interestComponents.length > 0) {
			return getEntitiesWithComponents(interestComponents);
		}
		return gm.getAllEntities();
	}

	public void awake() {}

	@Override
	public void fixedUpdate(float fixedDelta){}
	@Override
	public void update(float delta){}

	public boolean isEnabled() {
		return isEnabled;
	}

	public void setEnabled(boolean enabled) {
		isEnabled = enabled;
	}

	public Class<? extends IComponent>[] getInterestComponents() {
		return interestComponents;
	}

	public String getSystemName() {
		return this.getClass().getSimpleName();
	}

	public GameSystemInfo getSystemInfo() {
		return getClass().getAnnotation(GameSystemInfo.class);
	}
}
